﻿using Xunit;
using YAPL.Language.Ast;
using YAPL.Language.Ast.Transformation;
using YAPL.Language.Core.Types;

namespace YAPL.Test.YAPL.Language.Ast.Transformation {
	public class OperatorPrecomputationTransformTest {

		[Fact]
		public void BinaryExpressionWithConstantParametersShouldBeTrasformedIntoConstant() {
			var c1 = Expressions.Integer(1);
			var c2 = Expressions.Integer(2);
			var bin = Expressions.Binary(c1, c2, BinaryOperator.Plus);
			IAstTransform i = new OperatorPrecomputationTransform();
			var result = i.Transform(bin);
			Assert.IsType(typeof(ConstantExpression), result);
			var constant = (ConstantExpression) result;
			Assert.IsType(typeof(int), constant.Value);
			Assert.Equal(3, (int)constant.Value);
		}

		[Fact]
		public void UnaryExpressionWithConstantParametersShouldBeTrasformedIntoConstant() {
			var c = Expressions.Boolean(true);
			var unary = Expressions.Unary(c, UnaryOperator.Not);
			IAstTransform i = new OperatorPrecomputationTransform();
			var result = i.Transform(unary);
			Assert.IsType(typeof(ConstantExpression), result);
			var constant = (ConstantExpression)result;
			Assert.IsType(typeof (bool), constant.Value);
			Assert.Equal(false, (bool)constant.Value);
		}

		[Fact]
		public void ComplexExpressionWithConstantParametersShouldBeTrasformedIntoConstant() {
			var c1 = Expressions.Integer(1);
			var c2 = Expressions.Float(2.5);
			var c3 = Expressions.Float(0.5);
			var c4 = Expressions.Integer(5);
			var bin1 = Expressions.Binary(c1, c2, BinaryOperator.Plus);
			var bin2 = Expressions.Binary(c3, c4, BinaryOperator.Multiply);
			var rootBin = Expressions.Binary(bin1, bin2, BinaryOperator.Minus);
			IAstTransform i = new OperatorPrecomputationTransform();
			var result = i.Transform(rootBin);
			Assert.IsType(typeof(ConstantExpression), result);
			var constant = (ConstantExpression)result;
			Assert.IsType(typeof(double), constant.Value);
			Assert.Equal(1.0, (double)constant.Value);
		}
	}
}
